﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Plugins;
using Plugins.Core;
using Utils;

namespace StockAnalyst2.Plugins.Engine
{
	public class PluginDetector
	{
		#region Attributes

		private readonly string _folderToSearch;

		#endregion

		#region Public Methods

		public PluginDetector()
		{
			_folderToSearch = AppDomain.CurrentDomain.BaseDirectory;
		}

		public IEnumerable<Type> FindPlugins()
		{
			List<Type> result = new List<Type>();

			string[] assemblyFileNames = Directory.GetFiles(_folderToSearch, "*.dll");
			foreach (string assemblyFileName in assemblyFileNames)
			{
				try
				{
					if (!Properties.Settings.Default.ApplicationAssemblies.Contains(Path.GetFileName(assemblyFileName)))
					{
						Assembly assembly = Assembly.LoadFile(assemblyFileName);

						if (PluginDetector.IsPluginAssembly(assembly))
						{
							result.AddRange(PluginDetector.ExtractPluginTypesFromAssembly(assembly));
						}
					}
				}
				catch (Exception ex)
				{
					ExceptionLogger.LogException("Exception received while trying to load the assembly" + assemblyFileName + ". Skipping this assembly.", ex, false);
				}
			}

			return result;
		}

		#endregion

		#region Private Methods

		private static bool IsPluginAssembly(Assembly assembly)
		{
			return assembly.GetCustomAttributes(typeof(PluginContainerAssemblyAttribute), false).Length > 0;
		}

		private static IEnumerable<Type> ExtractPluginTypesFromAssembly(Assembly assembly)
		{
			List<Type> result = new List<Type>();

			foreach (Type type in assembly.GetTypes())
			{
				if (typeof(IStrategyPlugin).IsAssignableFrom(type))
				{
					result.Add(type);
				}
			}

			return result;
		}

		#endregion
	}
}
